﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace SpDisposeEx
{

    public class SpDisposeInfoDetail
    {
        public string ID { get; set; }
        public string Module { get; set; }
        public string Method { get; set; }
        public string Source { get; set; }
        public string Statement { get; set; }
        public string Notes { get; set; }
        public string MoreInformation { get; set; }
        public string Line { get; set; }
        public string WebText { get; set; }

    }
    [XmlRootAttribute("SpDisposeErrors")]
    public class SpDisposeInfoCollection : List<SpDisposeInfoDetail>
    {
    }
    public struct SpDisposeInfoTags
    {
        public const string ID = "ID:";
        public const string Module = "Module:";
        public const string Source = "Source:";
        public const string Line = "Line:";
        public const string Method = "Method:";
        public const string Statement = "Statement:";
        public const string Notes = "Notes:";
        public const string MoreInformation = "More Information:";
    }

    public class SPDisposerWatcher : IDisposable
    {
        private Process _process = null;
        private SpDisposeInfoCollection _disposeInfoList = null;

        /// <summary>
        /// Gets or sets the dispose info list.
        /// </summary>
        /// <value>The dispose info list.</value>
        public SpDisposeInfoCollection DisposeInfoList
        {
            get
            {
                return _disposeInfoList;
            }
            set
            {
                _disposeInfoList = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SpDisposeCheckAddIn"/> class.
        /// </summary>
        public SPDisposerWatcher()
        {
            _process = new Process();
            _disposeInfoList = new SpDisposeInfoCollection();
        }

        /// <summary>
        /// Gets the property.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private string GetProperty(string name, string value)
        {
            string tmp = String.Empty;
            tmp = value.Replace(name, "").Trim();
            if (name == SpDisposeInfoTags.ID)
            {
                tmp = tmp.Substring(0, tmp.Length - 1);
            }

            return tmp;
        }
        /// <summary>
        /// Determines whether the specified value has property.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="name">The name.</param>
        /// <returns>
        /// 	<c>true</c> if the specified value has property; otherwise, <c>false</c>.
        /// </returns>
        private bool HasProperty(string value, string name)
        {
            return value.Contains(name);
        }

        private string GetInfoXml()
        {
            string xml = String.Empty;
            if (DisposeInfoList.Count() > 0)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SpDisposeInfoCollection));
                StringWriter sw = new StringWriter();
                serializer.Serialize(sw, DisposeInfoList);
                xml = sw.ToString();
                sw.Close();
                sw.Dispose();
            }
            return xml;

        }
      
        private string GetInfo()
        {
            StringBuilder sb = new StringBuilder();
           
            foreach (SpDisposeInfoDetail inf in DisposeInfoList)
            {
               
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.ID);
                sb.Append(inf.ID);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.Module);
                sb.Append(inf.Module);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.Method);
                sb.Append(inf.Method);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.Source);
                sb.Append(inf.Source);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.Line);
                sb.Append(inf.Line);
                sb.Append("\n\r");               
                sb.Append(SpDisposeInfoTags.Statement);
                sb.Append(inf.Statement);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.Notes);
                sb.Append(inf.Notes);
                sb.Append("\n\r");
                sb.Append(SpDisposeInfoTags.MoreInformation);
                sb.Append(inf.MoreInformation);
                sb.Append("\n\r");
                sb.Append(new string('-', 80));


            }
            return sb.ToString();

        }
        public string ValidateDisposes(string spDisposeCheckToolFullPath, string arguments, bool xml)
        {
            string tmp = LaunchProcess(spDisposeCheckToolFullPath, arguments);
            if (tmp.IndexOf(":") != -1)
            {
                

                GetDisposeInformation(tmp);
                if (xml)
                    tmp = GetInfoXml();
                else
                    tmp = GetInfo();

            }
           

            return tmp;


        }
        /// <summary>
        /// Launches the process.
        /// </summary>
        private string LaunchProcess(string filenameToExecute, string arguments)
        {

            _process.StartInfo.RedirectStandardOutput = true;

            _process.StartInfo.Arguments = arguments;
            _process.StartInfo.CreateNoWindow = true;
            _process.StartInfo.UseShellExecute = false;
            _process.StartInfo.ErrorDialog = false;
            _process.StartInfo.FileName = filenameToExecute;
            _process.Start();

            StreamReader sReader = _process.StandardOutput;
            string results = sReader.ReadToEnd();
            sReader.Close();
            sReader.Dispose();
            sReader = null;

            return results;
        }

        private void GetDisposeInformation(string information)
        {
            SpDisposeInfoCollection lst = null;
            DisposeInfoList = null;
            SpDisposeInfoDetail inf = null;

            try
            {
                string[] lines = information.Split((char)13);

                //string[] lines = File.ReadAllLines(@"C:\Work\Dev\Gisp\SharePoint\Validation\SPDisposeCheck\t.txt");

                var items = from l in lines
                            where l.Contains(":")
                            select l;



                lst = new SpDisposeInfoCollection();
               
                foreach (var a in items)
                {
                    string tmp = a.ToString();

                    //Start
                    if (HasProperty(tmp, SpDisposeInfoTags.ID))
                    {
                        if (inf != null)
                            lst.Add(inf);
                        inf = new SpDisposeInfoDetail();
                        inf.ID = GetProperty(SpDisposeInfoTags.ID, tmp);
                    }

                    if (HasProperty(tmp, SpDisposeInfoTags.Module))
                    {
                        inf.Module = GetProperty(SpDisposeInfoTags.Module, tmp);
                    }

                    if (HasProperty(tmp, SpDisposeInfoTags.Method))
                    {
                        inf.Method = GetProperty(SpDisposeInfoTags.Method, tmp);
                    }
                    if (HasProperty(tmp, SpDisposeInfoTags.Source))
                    {
                        inf.Source = GetProperty(SpDisposeInfoTags.Source, tmp);
                    }

                    if (HasProperty(tmp, SpDisposeInfoTags.Statement))
                    {
                        inf.Statement = GetProperty(SpDisposeInfoTags.Statement, tmp);
                    }
                    if (HasProperty(tmp, SpDisposeInfoTags.Notes))
                    {
                        inf.Notes = GetProperty(SpDisposeInfoTags.Notes, tmp);
                    }
                    if (HasProperty(tmp, SpDisposeInfoTags.MoreInformation))
                    {
                        inf.MoreInformation = "<a href='" + GetProperty(SpDisposeInfoTags.MoreInformation, tmp) + "'>Link<a>";
                    }
                    if (HasProperty(tmp, SpDisposeInfoTags.Line))
                    {
                        inf.Line = GetProperty(SpDisposeInfoTags.Line, tmp);
                    }
                }
                DisposeInfoList = lst;
            }
            catch 
            {
               
            }
            if (inf != null && !DisposeInfoList.Contains(inf))
            {
                DisposeInfoList.Add(inf);
            }
           
        }







        #region IDisposable Members

        public void Dispose()
        {
            _process.Dispose();
            _process = null;
        }

        #endregion
    }
}
